﻿using System;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;

public class Painting : MonoBehaviour
{
    public Material brushMat;
    public Texture brushTypeTexture;   //画笔纹理，半透明 
    public Color brushColor = Color.black;
    public RawImage _drawImage;
    private RectTransform _deawAreaRect;
    public Camera uiCamera;
    protected RenderTexture _renderTex;   //画布
    [SerializeField]
    private float brushScale = 0.5f; //笔刷 缩放
    [SerializeField]
    [Tooltip("笔刷 粗细 比例")]
    [Range(0.1f, 1)]
    private float brushScalePix = 1f;

    private float lastDistance;
    private Vector3[] PositionArray = new Vector3[3];
    private int a = 0;
    private Vector3[] PositionArray1 = new Vector3[4];
    private int b = 0;
    private float[] speedArray = new float[4];
    private int s = 0;
    [SerializeField]
    [Tooltip("笔刷 稀疏度")]
    [Range(1, 200)]
    private int num = 50;

    Vector3 startPosition = Vector3.zero;
    Vector3 endPosition = Vector3.zero;


    private Vector2 RenderSize;
    protected Vector2 sceneSize;
    private Vector2 sceneSizePix = Vector2.one;//不同分辨率 系数
    protected bool isDrewingAgree = true; //同意 划线开关


    protected virtual void Start()
    {
        RenderSize = new Vector2();
        RenderSize.x = 1920;
        RenderSize.y = 1080;

        sceneSize = new Vector2();
        sceneSize.x = Screen.width;
        sceneSize.y = Screen.height;

        if (_deawAreaRect == null)
            _deawAreaRect = _drawImage.transform.parent.GetComponent<RectTransform>();

        _renderTex = new RenderTexture((int)RenderSize.x, (int)RenderSize.y, 24, RenderTextureFormat.ARGB32);
        _drawImage.texture = _renderTex;

        ClearRenderTexture(_renderTex);

        Canvas canvas = GetComponentInParent<Canvas>();
        if (canvas.renderMode == RenderMode.WorldSpace)
        {
            //InputEvent.Instance.AddAction(0, CommonUsagesType.TriggerButton, null, PicoStay, PicoEnd);
            uiCamera = canvas.worldCamera;
        }
    }
    private void OnDestroy()
    {
        if (uiCamera != null)
        {
            //InputEvent.Instance.RmoveAction(0, CommonUsagesType.TriggerButton, null, PicoStay, PicoEnd);
        }
    }



    void SetMat()
    {
        brushMat.SetTexture("_MainTex", brushTypeTexture);
        brushMat.SetColor("_Color", brushColor);
        brushMat.SetPass(0);
    }


    void Update()
    {
        if (!isDrewingAgree)
            return;

#if UNITY_STANDALONE_WIN || UNITY_EDITOR
        OnPc();
#elif UNITY_ANDROID || UNITY_IPHONE
      OnAndroid();
#endif

    }

    void OnPc()
    {
        if (Input.GetMouseButton(0))
        {
            OnDrag(Input.mousePosition);
        }
        if (Input.GetMouseButtonUp(0))
        {
            DragEnd();
        }
    }
    void OnAndroid()
    {
        int count = Input.touchCount;
        Touch tempTouch;
        for (int i = 0; i < count; i++)
        {
            tempTouch = Input.GetTouch(i);

            if (tempTouch.phase == TouchPhase.Moved)
            {
                OnDrag(tempTouch.position);
            }

            if (tempTouch.phase == TouchPhase.Ended)
            {
                DragEnd();
            }
        }
    }

    #region Pico 手柄 签名
    void PicoStay()
    {
        if (!isDrewingAgree)
            return;
        //UnityEngine.EventSystems.RaycastResult raycast = InputEvent.Instance.GetUIRaycast(0);
        //if (raycast.gameObject != null)
        //{
        //    OnDrag(raycast.screenPosition);
        //}
    }
    void PicoEnd()
    {
        if (!isDrewingAgree)
            return;
        DragEnd();
    }
    #endregion

    protected virtual void DragEnd()
    {
        startPosition = Vector3.zero;
        //brushScale = 0.5f;
        a = 0;
        b = 0;
        s = 0;


    }

    protected virtual void OnDrag(Vector3 pos)
    {
        pos.z = 0;

        endPosition = pos;
        float distance = Vector3.Distance(startPosition, endPosition);

        ThreeOrderBézierCurse(pos, distance, 4.5f);

        startPosition = endPosition;
        lastDistance = distance;

    }

    float SetBrushScale(float distance)  //设置画笔宽度
    {
        float Scale = 0;
        if (distance < 100)
        {
            Scale = 0.8f - 0.005f * distance;
        }
        else
        {
            Scale = 0.425f - 0.00125f * distance;
        }
        if (Scale <= 0.05f)
        {
            Scale = 0.05f;
        }
        return Scale;
    }

    void ClearRenderTexture(RenderTexture destTexture)
    {
        Graphics.SetRenderTarget(destTexture);
        GL.PushMatrix();
        GL.Clear(true, true, Color.white);
        GL.PopMatrix();
    }



    public void ResetRenderTex()
    {
        ClearRenderTexture(_renderTex);
    }
    public void SaveRenderImage()
    {
        SaveRenderImage("temp", "test");
    }
    public virtual void SaveRenderImage(string shotpath, string pngName)
    {
        PhotoHelp.SaveRenderTextureToPNG(_renderTex, shotpath, pngName);
        //ApiMgr.Instance.UpPhoto(_renderTex, pngName)
    }

    public void LoadRenderImage()
    {
        StartCoroutine(PhotoHelp.LoadRenderTexture("temp", "test", (tex) =>
        {
            if (_deawAreaRect.Find("Image"))
                _deawAreaRect.Find("Image").GetComponent<Image>().sprite = tex;
        }));
    }

    private void TwoOrderBézierCurse(Vector3 pos, float distance) //二阶贝塞尔曲线
    {
        PositionArray[a] = pos;
        a++;
        if (a == 3)
        {
            for (int index = 0; index < num; index++)
            {
                Vector3 middle = (PositionArray[0] + PositionArray[2]) / 2;
                PositionArray[1] = (PositionArray[1] - middle) / 2 + middle;

                float t = (1.0f / num) * index / 2;
                Vector3 target = Mathf.Pow(1 - t, 2) * PositionArray[0] + 2 * (1 - t) * t * PositionArray[1] +
                                 Mathf.Pow(t, 2) * PositionArray[2];
                float deltaSpeed = (float)(distance - lastDistance) / num;
                DrawBrush((int)target.x, (int)target.y, SetBrushScale(lastDistance + (deltaSpeed * index)));
            }
            PositionArray[0] = PositionArray[1];
            PositionArray[1] = PositionArray[2];
            a = 2;
        }
        else
        {
            DrawBrush((int)endPosition.x, (int)endPosition.y, SetBrushScale(distance));
        }
    }

    //三阶贝塞尔曲线，获取连续4个点坐标，通过调整中间2点坐标，画出部分（我使用了num/1.5实现画出部分曲线）来使曲线平滑;通过速度控制曲线宽度。
    private void ThreeOrderBézierCurse(Vector3 pos, float distance, float targetPosOffset)
    {
        //记录坐标
        PositionArray1[b] = pos;
        b++;
        //记录速度
        speedArray[s] = distance;
        s++;
        if (b == 4)
        {
            Vector3 temp1 = PositionArray1[1];
            Vector3 temp2 = PositionArray1[2];

            //修改中间两点坐标
            Vector3 middle = (PositionArray1[0] + PositionArray1[2]) / 2;
            PositionArray1[1] = (PositionArray1[1] - middle) * 1.5f + middle;
            middle = (temp1 + PositionArray1[3]) / 2;
            PositionArray1[2] = (PositionArray1[2] - middle) * 2.1f + middle;

            for (int index1 = 0; index1 < num / 1.5f; index1++)
            {
                float t1 = (1.0f / num) * index1;
                Vector3 target = Mathf.Pow(1 - t1, 3) * PositionArray1[0] +
                                 3 * PositionArray1[1] * t1 * Mathf.Pow(1 - t1, 2) +
                                 3 * PositionArray1[2] * t1 * t1 * (1 - t1) + PositionArray1[3] * Mathf.Pow(t1, 3);
                //float deltaspeed = (float)(distance - lastDistance) / num;
                //获取速度差值（存在问题，参考）
                float deltaspeed = (float)(speedArray[3] - speedArray[0]) / num;
                //float randomOffset = Random.Range(-1/(speedArray[0] + (deltaspeed * index1)), 1 / (speedArray[0] + (deltaspeed * index1)));
                //模拟毛刺效果
                float randomOffset = Random.Range(-targetPosOffset, targetPosOffset);
                DrawBrush((int)(target.x + randomOffset), (int)(target.y + randomOffset), SetBrushScale(speedArray[0] + (deltaspeed * index1)));
            }

            PositionArray1[0] = temp1;
            PositionArray1[1] = temp2;
            PositionArray1[2] = PositionArray1[3];

            speedArray[0] = speedArray[1];
            speedArray[1] = speedArray[2];
            speedArray[2] = speedArray[3];
            b = 3;
            s = 3;
        }
        else
        {
            DrawBrush((int)endPosition.x, (int)endPosition.y, SetBrushScale(distance));
        }
    }


    /// <summary>
    /// 同步签名 比例缩放
    /// </summary>
    /// <param name="_sceneSize"></param>
    public void SetSizePix(Vector2 _sceneSize)
    {
        SetSizePix(_sceneSize.x, _sceneSize.y);
    }
    public void SetSizePix(float scenceWith, float scenceHeight)
    {
        sceneSizePix.x = sceneSize.x / scenceWith; // 2560/ 1920;
        sceneSizePix.y = sceneSize.y / scenceHeight; // 1600/ 1080;
    }

    [SerializeField]
    private Rect temp = new Rect();
    void DrawBrush(int x, int y, float scale)
    {
        temp.x = x;
        temp.y = y;
        temp.width = brushTypeTexture.width;
        temp.height = brushTypeTexture.height;

        temp.x *= sceneSizePix.x;
        temp.y *= sceneSizePix.y;

        float viewWith = sceneSize.x;
        float viewHeight = sceneSize.y;
        brushScale = scale;
        scale *= brushScalePix;


        #region 坐标 转换

        if (!ScreenPointToLocalPointInRectangle(_deawAreaRect, ref temp))
            return;


        viewWith = _deawAreaRect.rect.width; //Screen.width
        viewHeight = _deawAreaRect.rect.height; //Screen.height

        float pix = RenderSize.x / viewWith;
        scale /= pix;
        #endregion

        DrawBrush(_renderTex, temp, scale, viewWith, viewHeight);
    }

    bool ScreenPointToLocalPointInRectangle(RectTransform _deawAreaRect, ref Rect temp)
    {
        float viewWith = _deawAreaRect.rect.width;
        float viewHeight = _deawAreaRect.rect.height;

        Vector2 localPoint;
        localPoint.x = temp.x;
        localPoint.y = temp.y;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(_deawAreaRect, localPoint, uiCamera, out localPoint);

        localPoint.x += viewWith / 2;
        localPoint.y += viewHeight / 2;

        if (localPoint.x < 0 || localPoint.x > viewWith || localPoint.y < 0 || localPoint.y > viewHeight)
            return false;

        temp.x = localPoint.x;
        temp.y = localPoint.y;

        return true;
    }

    void DrawBrush(RenderTexture destTexture, Rect destRect, float scale, float viewWith, float viewHeight)
    {
        float left = destRect.xMin - destRect.width * scale / 2.0f;
        float right = destRect.xMin + destRect.width * scale / 2.0f;
        float top = destRect.yMin - destRect.height * scale / 2.0f;
        float bottom = destRect.yMin + destRect.height * scale / 2.0f;

        Graphics.SetRenderTarget(destTexture);

        GL.PushMatrix();
        GL.LoadOrtho();

        GL.Begin(GL.QUADS);

        SetMat();

        GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(left / viewWith, top / viewHeight, 0);
        GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(right / viewWith, top / viewHeight, 0);
        GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(right / viewWith, bottom / viewHeight, 0);
        GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(left / viewWith, bottom / viewHeight, 0);

        GL.End();
        GL.PopMatrix();
    }
}
